package org.jeecg.modules.xindian.reconciliation.controller;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.xindian.reconciliation.controller.req.EditPolicyReq;
import org.jeecg.modules.xindian.reconciliation.controller.req.IdWapper;
import org.jeecg.modules.xindian.reconciliation.controller.req.PolicyRelationExcel;
import org.jeecg.modules.xindian.reconciliation.controller.req.ReportReq;
import org.jeecg.modules.xindian.reconciliation.controller.rsp.BrokerageFeeSettlementInfoExcel;
import org.jeecg.modules.xindian.reconciliation.controller.rsp.ChannelBrokerageFeeSettlementInfo;
import org.jeecg.modules.xindian.reconciliation.controller.rsp.ChannelSettlementPolicyInfoExcel;
import org.jeecg.modules.xindian.reconciliation.controller.rsp.SettlementPolicyInfoExcel;
import org.jeecg.modules.xindian.reconciliation.entity.ChannelSettlementConfig;
import org.jeecg.modules.xindian.reconciliation.entity.ChannelSettlementInfo;
import org.jeecg.modules.xindian.reconciliation.enums.DeleteFlagEnum;
import org.jeecg.modules.xindian.reconciliation.mapper.PolicySettlementStatisticsMapper;
import org.jeecg.modules.xindian.reconciliation.service.IChannelSettlementConfigService;
import org.jeecg.modules.xindian.reconciliation.service.IChannelSettlementInfoService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Api(tags = "渠道结算模块")
@RestController
@RequestMapping("/settlement/channel")
@Slf4j
public class ChannelSettlementController {
    @Autowired
    private IChannelSettlementConfigService channelSettlementConfigService;
    @Autowired
    private IChannelSettlementInfoService iChannelSettlementInfoService;

    @Autowired
    private PolicySettlementStatisticsMapper settlementInfoMapper;
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    /**
     * 账单周期记录
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "账单周期记录", notes = "账单周期记录")
    @PostMapping(value = "/info")
    public Result<IPage<ChannelSettlementInfo>> info(@RequestBody ReportReq req) {
        log.info("账单周期请求参数如下:{}", req);
        Assert.notNull(req.getPageSize(), "页数不能为空");
        Assert.notNull(req.getPageIndex(), "页码不能为空");
        Assert.notBlank(req.getDate(), "账单周期不能为空");
        IPage<ChannelSettlementInfo> page = new Page<>(req.getPageIndex(), req.getPageSize());
        return Result.ok(iChannelSettlementInfoService.queryChannelSettlementInfo(page,req.getDate()));
    }


    /**
     * 账单周期记录
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "未结算的账单周期记录", notes = "未结算的账单周期记录")
    @PostMapping(value = "/unSettlementlInfoList")
    public Result<IPage<ChannelSettlementInfo>> unSettlementlInfoList(@RequestBody ReportReq req) {
        log.info("账单周期请求参数如下:{}", req);
        Assert.notNull(req.getPageSize(), "页数不能为空");
        Assert.notNull(req.getPageIndex(), "页码不能为空");
        Assert.notBlank(req.getDate(), "账单周期不能为空");
        IPage<ChannelSettlementInfo> page = new Page<>(req.getPageIndex(), req.getPageSize());
        return Result.ok(iChannelSettlementInfoService.queryChannelUnSettlementInfo(page,req.getDate()));
    }

    /**
     * 同步上个月数据
     *
     * @return
     */
    @ApiOperation(value = "同步上个月数据", notes = "同步上个月数据")
    @PostMapping(value = "/synchronizeLastMonth")
    public Result<?> synchronizeLastMonth() {
        iChannelSettlementInfoService.synchronizeLastMonth();
        return Result.ok();
    }

    /**
     * 上传保单
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "上传保单", notes = "上传保单")
    @PostMapping(value = "/uploadEditPolicy")
    public Result<?> uploadPolicy(@RequestBody EditPolicyReq editPolicyReq) {
        return uploadPolicyFile(editPolicyReq);
    }


    private Result<?> uploadPolicyFile(EditPolicyReq editPolicyReq) {
        Assert.notNull(editPolicyReq.getId(), "结算记录Id不能为空");
        Assert.notNull(editPolicyReq.getUrl(), "文件地址不能为空");
        String id = editPolicyReq.getId();
        // 获取上传文件对象
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(uploadpath + File.separator+editPolicyReq.getUrl());
            ImportParams params = new ImportParams();
            params.setTitleRows(0);
            params.setHeadRows(0);
            params.setNeedSave(true);
            List<PolicyRelationExcel> list = ExcelImportUtil.importExcel(fileInputStream, PolicyRelationExcel.class, params);
            AtomicReference<Integer> rowId = new AtomicReference<>(1);
            List<String> relations = list.stream().map(pt -> {
                rowId.getAndSet(rowId.get() + 1);
                Assert.notBlank(pt.getPolicyNo(), "第{}行保单号为空", rowId.get());
                return pt.getPolicyNo();
            }).collect(Collectors.toList());
            //计算统计信息
            iChannelSettlementInfoService.loadSettlementByUpLoadFile(id, relations);
            return Result.OK("文件导入成功！数据行数:" + list.size());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("文件导入失败:" + e.getMessage());
        } finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                log.error("关闭资源失败", e);
            }
        }
    }


    /**
     * 确认保单
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "确认保单", notes = "确认保单")
    @PostMapping(value = "/confirmPolicy")
    public Result<?> confirmPolicy(@RequestBody IdWapper idWapper) {
        Assert.notNull(idWapper.getId(), "数据主键不能为空");
        iChannelSettlementInfoService.confirmPolicy(idWapper.getId());
        return Result.ok();
    }

    /**
     * 保单明细
     * @param request
     */
    //@RequiresPermissions("banck:insurance_hangzhou_back:exportXls")@\
    @ApiOperation(value = "保单明细导出", notes = "保单明细导出")
    @GetMapping(value = "/exportXlsPolicyInfo")
    public ModelAndView exportXlsPolicyInfo(IdWapper idWapper,HttpServletRequest request) {
        Assert.notNull(idWapper.getId(), "数据主键不能为空");
        List<ChannelSettlementPolicyInfoExcel> policyInfoExcels = settlementInfoMapper.queryChannelPolicyInfo(idWapper.getId());
        return this.exportXls(request, policyInfoExcels, ChannelSettlementPolicyInfoExcel.class, "保单明细");
    }


    /**
     * 保单明细
     * @param request
     */
    //@RequiresPermissions("banck:insurance_hangzhou_back:exportXls")@\
    @ApiOperation(value = "保单未结算明细导出", notes = "保单未结算明细导出")
    @GetMapping(value = "/exportXlsUnSettlementPolicyInfo")
    public ModelAndView exportXlsUnSettlementPolicyInfo(IdWapper idWapper,HttpServletRequest request) {
        Assert.notNull(idWapper.getId(), "数据主键不能为空");
        List<ChannelSettlementPolicyInfoExcel> policyInfoExcels = settlementInfoMapper.queryChannelUnSettlementPolicyInfo(idWapper.getId());
        return this.exportXls(request, policyInfoExcels, ChannelSettlementPolicyInfoExcel.class, "保单明细");
    }


    /**
     * 经纪费明细
     *
     * @param idWapper
     */
    //@RequiresPermissions("banck:insurance_hangzhou_back:exportXls")@\
    @ApiOperation(value = "经纪费明细", notes = "经纪费明细")
    @GetMapping(value = "/exportXlsBrokerageFeeInfo")
    public ModelAndView exportXlsBrokerageFeeInfo(IdWapper idWapper, HttpServletRequest request) {
        Assert.notNull(idWapper.getId(), "数据主键不能为空");
        List<BrokerageFeeSettlementInfoExcel> policyInfoExcels = settlementInfoMapper.queryChannelFeeBySettlementId(idWapper.getId());
        return this.exportXls(request, policyInfoExcels, BrokerageFeeSettlementInfoExcel.class, "经纪费明细");
    }

    /**
     * 经纪费结算单
     * @param idWapper
     */
    //@RequiresPermissions("banck:insurance_hangzhou_back:exportXls")@\
    @ApiOperation(value = "经纪费结算单", notes = "经纪费结算单")
    @GetMapping(value = "/exportXlsBrokerageFeeSettlementInfo")
    public ModelAndView exportXlsBrokerageFeeSettlementInfo(IdWapper idWapper, HttpServletRequest request) {
           List<ChannelBrokerageFeeSettlementInfo> policyInfoExcels = settlementInfoMapper.listByIdChannelBrokerageFeeSettlementInfos(idWapper.getId());
            AtomicReference<Integer> i = new AtomicReference<>(1);
           //计算开票金额
            policyInfoExcels.forEach(one->{
                one.setSeq(i.get());
                BigDecimal kaiPiaoAmt = one.getChannelFree().add(one.getChannelAloneFee());
                one.setKaiPiaoAmt(kaiPiaoAmt);
                i.getAndSet(i.get() + 1);
            });
        return this.exportXls(request, policyInfoExcels, ChannelBrokerageFeeSettlementInfo.class, "杭州筑保科技有限公司业务结算单");
    }


    /**
     * 导出excel
     *
     * @param request
     */
    protected <T> ModelAndView exportXls(HttpServletRequest request, List<T> exportList, Class<T> clazz, String title) {
        // Step.1 组装查询条件
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // Step.3 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        //此处设置的filename无效 ,前端会重更新设置一下
        mv.addObject(NormalExcelConstants.FILE_NAME, title);
        mv.addObject(NormalExcelConstants.CLASS, clazz);
        //update-begin--Author:liusq  Date:20210126 for：图片导出报错，ImageBasePath未设置--------------------
        ExportParams exportParams = new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title);
        exportParams.setType(ExcelType.HSSF);
        mv.addObject(NormalExcelConstants.PARAMS, exportParams);
        mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
        return mv;
    }


    /**
     * 分页列表查询
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    //@AutoLog(value = "渠道结算配置-分页列表查询")
    @ApiOperation(value = "渠道结算配置-分页列表查询", notes = "渠道结算配置-分页列表查询")
    @GetMapping(value = "/configList")
    public Result<IPage<ChannelSettlementConfig>> configList(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        Page<ChannelSettlementConfig> page = new Page<ChannelSettlementConfig>(pageNo, pageSize);
        IPage<ChannelSettlementConfig> pageList = channelSettlementConfigService.lambdaQuery().page(page);
        pageList.getRecords().forEach(ChannelSettlementConfig::buildConfigBean);
//        pageList.getRecords().forEach(ChannelSettlementConfig::buildAreas);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param channelSettlementConfig
     * @return
     */
    @AutoLog(value = "渠道结算配置-添加")
    @ApiOperation(value = "渠道结算配置-添加", notes = "渠道结算配置-添加")
    //@RequiresPermissions("reconciliation:channel_settlement_config:add")
    @PostMapping(value = "/add")
    public Result<String> add(@RequestBody ChannelSettlementConfig channelSettlementConfig) {
        channelSettlementConfig.setDeleteFlag(DeleteFlagEnum.N);
        channelSettlementConfigService.save(channelSettlementConfig);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param channelSettlementConfig
     * @return
     */
    @AutoLog(value = "渠道结算配置-编辑")
    @ApiOperation(value = "渠道结算配置-编辑", notes = "渠道结算配置-编辑")
    //@RequiresPermissions("reconciliation:channel_settlement_config:edit")
    @PostMapping(value = "/edit")
    public Result<String> edit(@RequestBody ChannelSettlementConfig channelSettlementConfig) {
        channelSettlementConfigService.updateById(channelSettlementConfig);
        return Result.OK("编辑成功!");
    }


}
